//
//  ErrorHandleObservableViewController.swift
//  Example
//
//  Created by T AO on 2022/2/10.
//

import UIKit
import RxSwift

class ErrorHandleObservableViewController: BaseViewController {
    
    enum MyError: Error {
        case A
        case B
    }

    override func viewDidLoad() {
        super.viewDidLoad()

//        catchAndReturn()
//        catchError()
        retry()
    }

}

// MARK: - 从可观察对象的错误通知中恢复的操作符

extension ErrorHandleObservableViewController {
    /// catchAndReturn
    /// 当遇到 error 事件的时候，就返回指定的值，然后结束
    private func catchAndReturn() {
        let failSubject = PublishSubject<String>()
        
        failSubject
            .catchAndReturn("错误")
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        
        failSubject.onNext("a")
        failSubject.onNext("b")
        failSubject.onNext("c") // 正常序列发送成功的
        
        // 发送失败的序列，一旦订阅到，返回我们之前设定的错误的预案
        failSubject.onError(MyError.A)
        
        failSubject.onNext("d")
    }
    
    /// catch
    /// 该方法可以捕获 error，并对其进行处理
    /// 同时还能返回另一个 Observable 序列进行订阅（切换到新的序列）
    private func catchError() {
        let subject = PublishSubject<String>()
        let recoverySequence = Observable.of("1", "2", "3")
        
        subject
            .catch {
                print("error: \($0)")
                // 获取到了错误序列，我们在中间的闭包操作处理完毕，返回给用户需要的序列(showAlert)
                return recoverySequence
            }
            .subscribe { print($0) }
            .disposed(by: disposeBag)
        
        subject.onNext("aaa")
        subject.onNext("bbb")   // 正常序列发送成功的
        
        // 发送失败的序列
        subject.onError(MyError.B)
        
        subject.onNext("ccc")
    }
    
    /// retry
    /// 当遇到错误的时候，会重新订阅该序列。比如遇到网络请求失败时，可以进行重新连接
    /// 可以传入数字表示重试次数。不传的话只会重试一次
    private func retry() {
        var count = 1   // 外界变量控制流程
        let observable = Observable<String>.create { observer in
            observer.onNext("Germ")
            observer.onNext("TAO")
            observer.onNext("AAA")
            
            if count == 1 {
                // 流程进来之后就会过度-这里的条件可以作为出口，失败的次数
                
                // 接收到错误序列，重试
                observer.onError(MyError.A)
                
                print("错误序列来了")

                count += 1
            }
            
            observer.onNext("aaa")
            observer.onNext("bbb")
            observer.onNext("ccc")
            observer.onCompleted()
            
            return Disposables.create()
        }
        
        observable
            .retry()
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
    }
}
